﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using CKSE.Interfaces;

namespace Skyrim
{
    public class SkyrimCompiler : ICompiler
    {
        #region Events
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler CompilationCompleted;

        private delegate void CompileByScriptDelegate(IScript script);
        private delegate void CompileByNameDelegate(string scriptName);
        private delegate void CompileAllDelegate();
        #endregion

        #region Fields
        private readonly object _syncRoot = new object();
        private IGame _game;
        private bool _isBusy;
        #endregion

        #region Properties
        /// <summary>
        /// 
        /// </summary>
        public object SyncRoot
        {
            get
            {
                return _syncRoot;
            }
        }
        /// <summary>
        /// Renvoie True si une compilation est en cours, False sinon.
        /// </summary>
        public bool IsBusy
        {
            get
            {
                return _isBusy;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        public IGame Game
        {
            get
            {
                return _game;
            }
        }
        #endregion


        #region Life Cycle
        /// <summary>
        /// 
        /// </summary>
        /// <param name="game"></param>
        public SkyrimCompiler(IGame game)
        {
            _game = game;
        }
        #endregion

        #region Methods

        #region Async Methods
        /// <summary>
        /// 
        /// </summary>
        /// <param name="scriptName"></param>
        public void CompileAsync(string scriptName)
        {
            CompileByNameDelegate worker = new CompileByNameDelegate(Compile);
            AsyncCallback callback = new AsyncCallback(CompileAsyncEnd);

            lock (_syncRoot)
            {
                if (_isBusy)
                {
                    throw new InvalidOperationException("Compiler is busy...");
                }

                AsyncOperation async = AsyncOperationManager.CreateOperation(null);
                worker.BeginInvoke(scriptName, callback, async);
                _isBusy = true;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ias"></param>
        private void CompileAsyncEnd(IAsyncResult ias)
        {
            _isBusy = false;

            dynamic worker = ((AsyncResult)ias).AsyncDelegate;
            AsyncOperation async = (AsyncOperation)ias.AsyncState;
            worker.EndInvoke(ias);

            lock (_syncRoot)
            {
                _isBusy = false;
            }

            OnCompilationCompleted();
        }
        /// <summary>
        /// 
        /// </summary>
        public void CompileAllAsync()
        {
            CompileAllDelegate worker = new CompileAllDelegate(CompileAll);
            AsyncCallback callback = new AsyncCallback(CompileAsyncEnd);

            lock (_syncRoot)
            {
                if (_isBusy)
                {
                    throw new InvalidOperationException("Compiler is busy...");
                }

                AsyncOperation async = AsyncOperationManager.CreateOperation(null);
                worker.BeginInvoke(callback, async);
                _isBusy = true;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="script"></param>
        public void CompileAsync(IScript script)
        {
            CompileByScriptDelegate worker = new CompileByScriptDelegate(Compile);
            AsyncCallback callback = new AsyncCallback(CompileAsyncEnd);

            lock (_syncRoot)
            {
                if (_isBusy)
                {
                    throw new InvalidOperationException("Compiler is busy...");
                }

                AsyncOperation async = AsyncOperationManager.CreateOperation(null);
                worker.BeginInvoke(script, callback, async);
                _isBusy = true;
            }
        }
        #endregion
        /// <summary>
        /// 
        /// </summary>
        /// <param name="scriptName"></param>
        public void Compile(string scriptName)
        {
            lock (_syncRoot)
            {
                _isBusy = true;

                throw new NotImplementedException();

                _isBusy = false;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="script"></param>
        public void Compile(IScript script)
        {
            lock (_syncRoot)
            {
                _isBusy = true;

                throw new NotImplementedException();

                _isBusy = false;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        public void CompileAll()
        {
            lock (_syncRoot)
            {
                _isBusy = true;

                throw new NotImplementedException();

                _isBusy = false;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        protected virtual void OnCompilationCompleted()
        {
            EventHandler handler = CompilationCompleted;
            if (handler != null)
            {
                handler(this, null);
            }
        }
        #endregion
    }
}
